package com.wushijia.java8.lambda;

import com.wushijia.model.Phone;
import com.wushijia.model.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;

public class Chapter5 {

  public static void main(String[] args) {
    //上下文类型推断，不必写x的类型，以后可能有本地变量类型推断，var x = ...
    Function<Integer, Boolean> p = x -> x > 1;

    List<User> userList = new ArrayList<>();
    userList.add(new User("风清扬", "男", 45));
    userList.add(new User("令狐冲", "男", 24));
    userList.add(new User("岳灵珊", "女", 21));
    userList.add(new User("任盈盈", "女", 22));

    //声明一个空的Optional
    Optional<Phone> nullPhone = Optional.empty();
    //依据一个非空值创建Optional
    Phone phone = new Phone("小米", 1999d);
    Optional<Phone> phone1 = Optional.of(phone);

    Optional<User> optUser = Optional.ofNullable(new User("任我行", "男", 55, phone1));
    Optional<String> user = optUser.map(User::getName);
    System.out.println(user.get());

    //可接受null的Optional
    Phone phone2 = null;
    Optional<Phone> nullablePhone = Optional.ofNullable(phone2);

    //无需检查null
    Optional<String> name = phone1.map(Phone::getName);
    System.out.println(name.orElse("noknown"));

    Optional<Phone> phone3 = optUser.flatMap(User::getPhone);
    System.out.println(phone3.map(Phone::getName).get().equals(phone3.get().getName()));

    //由此可以说明，第一个map返回的值是Optional<<Optional<Phone>>>，第二个map返回的值是Optional<Phone>
    Object phoneByMap = ((Optional<Phone>) optUser.map(User::getPhone).map(Optional::get)).get().getName();
    System.out.println(phoneByMap);

    //使用flatap则只会返回一层Optional<Phone>
    String phoneByFlatMap = optUser.flatMap(User::getPhone).map(Phone::getName).orElse("Noknown");
    System.out.println(phoneByFlatMap);

    //filter
    Double phonePrice = optUser.filter(user1 -> "男".equals(user1.getSex())).flatMap(User::getPhone).map(Phone::getPrice).orElse(1998d);
    System.out.println(phonePrice);

    Properties props = new Properties();
    props.setProperty("a", "5");
    props.setProperty("b", "t");
    System.out.println(readDuration(props, "a"));
    System.out.println(readDurationByOptional(props, "b"));
  }


  private static int readDuration(Properties properties, String name) {
    String value = properties.getProperty(name);
    if (value != null) {
      try {
        int i = Integer.parseInt(value);
        if (i > 0) {
          return i;
        }
      } catch (NumberFormatException e) {
        e.printStackTrace();
      }
    }
    return 0;
  }

  private static Optional<Integer> stringToInt(String name) {
    try {
      return Optional.of(Integer.parseInt(name));
    } catch (NumberFormatException e) {
      return Optional.empty();
    }
  }

  private static int readDurationByOptional(Properties properties, String name) {
    String value = properties.getProperty(name);
    return Optional.ofNullable(value).flatMap(Chapter5::stringToInt).filter(i -> i > 0).orElse(0);
  }

}
